<?php

namespace app\admin\controller;

use app\admin\model\Branch;
use app\admin\model\NewVoucher;
use app\common\controller\Backend;
use app\common\library\Auth;
use fast\Random;
use PhpOffice\PhpSpreadsheet\IOFactory;
use think\Db;
use think\exception\PDOException;
use think\exception\ValidateException;
use think\Exception;

/**
 * 物品账户
 *
 * @icon fa fa-circle-o
 */
class VoucherAccount extends Backend
{
    
    /**
     * VoucherAccount模型对象
     * @var \app\admin\model\VoucherAccount
     */
    protected $model = null;

    protected $relationSearch = true;
    
    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\VoucherAccount;

    }

     /**
     * 查看
     */
    public function index()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if ($this->request->isAjax()) {
            //如果发送的来源是Selectpage，则转发到Selectpage
            if ($this->request->request('keyField')) {
                return $this->selectpage();
            }
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();

            $list = $this->model
                ->with(['newVoucher', 'branch'])
                ->where($where)
                ->order($sort, $order)
                ->paginate($limit);

            $result = array("total" => $list->total(), "rows" => $list->items());

            return json($result);
        }
        return $this->view->fetch();
    }

    /**
     * 添加
     *
     * @return string
     * @throws \think\Exception
     */
    public function add()
    {
        if (false === $this->request->isPost()) {
            return $this->view->fetch();
        }
        $params = $this->request->post('row/a');
        if (empty($params)) {
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $params = $this->preExcludeFields($params);

        if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
            $params[$this->dataLimitField] = $this->auth->id;
        }
        $result = false;
        Db::startTrans();
        try {
            //是否采用模型验证
            if ($this->modelValidate) {
                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
                $this->model->validateFailException()->validate($validate);
            }
            //判断数量
            if($params['total_number'] < 0){
                $this->error('请填写正确的总数量');
            }
            //判断账户是否存在
            $data = $this->model->where('branch_id',$params['branch_id'])->where('voucher_id',$params['voucher_id'])->where('admin_id',$this->auth->id)->find();
            if($data){
                $this->error('该账户已存在,请勿重复添加');
            }

            $result = $this->model->allowField(true)->save($params);
            Db::commit();
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if ($result === false) {
            $this->error(__('No rows were inserted'));
        }
        $this->success();
    }

    public function import()
    {
        if ($this->request->isPost()) {
            $file = $this->request->request('file');
            if (!$file) {
                $this->error(__('Parameter %s can not be empty', 'file'));
            }
            $filePath = ROOT_PATH . DS . 'public' . DS . $file;
            if (!is_file($filePath)) {
                $this->error(__('No results were found'));
            }
            //实例化reader
            $ext = pathinfo($filePath, PATHINFO_EXTENSION);
            if (!in_array($ext, ['xls', 'xlsx'])) {
                $this->error(__('Unknown data format'));
            }

            // 2. 解析Excel并过滤空行（假设表头：A=支行名称，B=商品名称，C=数量）
            try {
                $spreadsheet = IOFactory::load($filePath);
                $sheet = $spreadsheet->getActiveSheet();
                $data = $sheet->toArray(null, false, true, true); // 带表头的数组
                $header = array_shift($data); // 移除表头（保留用于错误提示的列名）
            } catch (\Exception $e) {
                $this->error('Excel解析失败：' . $e->getMessage());
            }

            // 过滤空行（支行名称和商品名称都为空的行视为无效）
            $validRows = array_filter($data, function ($row) {
                $branchName = trim($row['A'] ?? '');
                return !empty($branchName);
            });
            // 重置索引并记录原始行号（方便错误提示，原始行号=索引+2，因为表头是第1行）
            $validRows = array_values($validRows);
            if (empty($validRows)) {
                $this->error('Excel中无有效数据行');
            }
            // 3. 提取所有支行名称并校验存在性
            $branchNames = array_unique(array_map(function ($row) {
                return trim($row['A']); // 直接返回字符串，array_map后是一维数组
            }, $validRows));
            // 查询数据库中存在的支行
            $existBranches = Branch::where('name', 'in', $branchNames)->where('admin_id',$this->auth->id)->column('name', 'id');
            $existBranchNames = array_values($existBranches);
            // 找出不存在的支行
            $notExistBranches = array_diff($branchNames, $existBranchNames);
            if (!empty($notExistBranches)) {
                $this->error('以下支行不存在，请检查：' . implode('、', $notExistBranches));
            }
            // 建立“支行名称→ID”映射（键为名称，值为ID）
            $branchMap = array_flip($existBranches);
            // 4. 提取所有商品名称，建立“商品名称→ID”映射（不存在则创建）
            $goodsNames = array_unique(array_map(function ($row) {
                return trim($row['B']); // 直接返回字符串，array_map后是一维数组
            }, $validRows));

            // 查询已存在的商品
            $existGoods = NewVoucher::where('name', 'in', $goodsNames)->where('type',2)->where('admin_id',$this->auth->id)->column('name', 'id');
            $existGoodsNames = array_values($existGoods);
            // 建立已存在商品的映射
            $goodsMap = array_flip($existGoods);
            // 创建不存在的商品
            $newGoodsNames = array_diff($goodsNames, $existGoodsNames);
            if (!empty($newGoodsNames)) {
                $newGoodsData = array_map(function ($name) {
                    return ['name' => $name, 'type' => 2,'admin_id' => $this->auth->id,'createtime' => time()];
                }, $newGoodsNames);
                try {
                    // 插入新商品，返回成功插入的数量
                    $insertCount = NewVoucher::insertAll($newGoodsData);
                    if ($insertCount > 0) {
                        // 关键：通过名称查询刚插入的商品，获取ID（依赖name字段唯一）
                        $newGoods = NewVoucher::where('name', 'in', $newGoodsNames)
                                ->where('type', 2)
                                ->where('admin_id', $this->auth->id)
                                ->column('id', 'name'); // 返回 [名称 => ID] 的数组
                        // 补充到商品映射中
                        foreach ($newGoods as $name => $id) {
                            $goodsMap[$name] = $id;
                        }
                    }
                } catch (Exception $e) {
                    $this->error('创建商品失败：' . $e->getMessage());
                }
            }

            // 5. 逐行校验数据并组装库存数据
            $inventoryData = [];
            $errors = []; // 记录错误行信息
            foreach ($validRows as $index => $row) {
                $rowNum = $index + 2; // 原始行号（表头+当前索引+1）
                $branchName = trim($row['A']);
                $goodsName = trim($row['B']);
                $quantity = $row['C'] ?? '';

                // 校验支行ID（理论上不会失败，因为已提前校验）
                if (!isset($branchMap[$branchName])) {
                    $errors[] = "第{$rowNum}行：支行[{$branchName}]不存在";
                    continue;
                }
                $branchId = $branchMap[$branchName];

                // 校验商品ID（理论上不会失败，不存在的已创建）
                if (!isset($goodsMap[$goodsName])) {
                    $errors[] = "第{$rowNum}行：商品[{$goodsName}]未找到";
                    continue;
                }
                $goodsId = $goodsMap[$goodsName];

                // 校验数量：必须是数字且≥0
                if (!is_numeric($quantity)) {
                    $errors[] = "第{$rowNum}行：数量[{$quantity}]不是有效数字";
                    continue;
                }
                $quantity = (float)$quantity;
                if ($quantity < 0) {
                    $errors[] = "第{$rowNum}行：数量[{$quantity}]不能小于0";
                    continue;
                }

                //判断账户是否存在了
                $account = $this->model->where('branch_id',$branchId)->where('voucher_id',$goodsId)->where('admin_id',$this->auth->id)->find();
                if($account){
                    $errors[] = "第{$rowNum}行：该商品账户已存在";
                    continue;
                }

                // 组装库存数据（如需去重/更新，可在此处判断是否已有相同branch_id和goods_id的记录）
                $inventoryData[] = [
                    'branch_id' => $branchId,
                    'voucher_id' => $goodsId,
                    'total_number' => $quantity,
                    'createtime' => time(),
                    'admin_id' => $this->auth->id,
                ];
            }

            // 6. 处理错误
            if (!empty($errors)) {
                return $this->error('导入失败，错误如下：<br>' . implode('<br>', $errors));
            }
            // 7. 事务中批量插入库存数据
            try {
                Db::startTrans();
                $this->model->insertAll($inventoryData);
                Db::commit();
                $this->success('导入成功，共导入' . count($inventoryData) . '条库存记录');
            } catch (Exception $e) {
                Db::rollback();
                $this->error('插入库存数据失败：' . $e->getMessage());
            }
        }
        return $this->fetch('import');
    }


}
